﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace WebServer.Modules
{
	/// <summary>
	/// Provides a logging service
	/// </summary>
	[CoreModule("Logging", typeof(Logging), CoreModulePriority.Medium)]
	public static class Logging
	{
		private static string _OutputDirectory = IOUtility.GetSafeDirectoryPath(Core.BaseDirectory + "\\" + Config.SystemName + "\\Logs\\");
		public static string OutputDirectory
		{
			get
			{
				if (String.IsNullOrEmpty(_OutputDirectory))
					_OutputDirectory = IOUtility.GetSafeDirectoryPath(Core.BaseDirectory + "\\" + Config.SystemName + "\\Logs\\");

				return _OutputDirectory;
			}
			set { _OutputDirectory = IOUtility.GetSafeDirectoryPath(value); }
		}

		/// <summary>
		/// Initializes the logging service
		/// </summary>
		private static void Start()
		{
			Events.CoreMessage += new CoreMessageHandler(Events_CoreMessage);

			IOUtility.EnsureDirectory(_OutputDirectory);
			IOUtility.EnsureDirectory(_OutputDirectory + "\\Clients\\");
			IOUtility.EnsureDirectory(_OutputDirectory + "\\Errors\\");
		}

		private static void Events_CoreMessage(CoreMessageEventArgs e)
		{
			if (e.Handled)
				return;

			switch (e.Action)
			{
				case CoreMessageAction.Error: { WriteError(e.Message); } break;
			}
		}

		/// <summary>
		/// Writes a formatted error to the error log file
		/// </summary>
		/// <param name="format">String format</param>
		/// <param name="args">Format arguments</param>
		public static void WriteError(string format, object[] args)
		{
			WriteError(String.Format(format, args));
		}

		/// <summary>
		/// Writes an error to the error log file
		/// </summary>
		/// <param name="error">Error message to write</param>
		public static void WriteError(string error)
		{
			WriteError(new string[] { error });
		}

		/// <summary>
		/// Writes multiple errors to the error log file
		/// </summary>
		/// <param name="errors">List of lines to write</param>
		public static void WriteError(string[] errors)
		{
			try
			{
				if (!Config.ErrorLogging)
					return;

				DirectoryInfo di = IOUtility.EnsureDirectory(_OutputDirectory + "\\Errors\\");

				string filePath = IOUtility.GetSafeFilePath(di.FullName + DateTime.Now.ToLongDateString() + ".html", true);

				FileInfo info = new FileInfo(filePath);

				if (!info.Exists)
				{
					using (StreamWriter writer = new StreamWriter(info.Create(), Encoding.Default))
					{

						writer.WriteLine("<HTML>");
						writer.WriteLine("<HEAD><TITLE>{0}</TITLE></HEAD>", info.Name);
						writer.WriteLine("<BODY>");
						writer.WriteLine("<CENTER>");

						writer.Flush();
						writer.Close();
					}
				}

				using (StreamWriter writer = new StreamWriter(info.FullName, true))
				{
					for (int i = 0; i < errors.Length; i++)
					{
						writer.WriteLine("<TABLE WIDTH=\"90%\" CELLSPACING=\"0\" CELLPADDING=\"5\" BORDER=\"1\">");
						writer.WriteLine("<TR><TD WIDTH=\"7%\">");
						writer.WriteLine(DateTime.Now.ToShortTimeString());
						writer.WriteLine("</TD><TD WIDTH=\"93%\">");
						writer.WriteLine(errors[i]);
						writer.WriteLine("</TD></TR>");
						writer.WriteLine("</TABLE>");
					}

					writer.Flush();
					writer.Close();
				}
			}
			catch { }
		}

		/// <summary>
		/// Writes a formatted line to the log file for the given Client
		/// </summary>
		/// <param name="client">Client connection</param>
		/// <param name="format">String format</param>
		/// <param name="args">Format arguments</param>
		public static void WriteLine(Client client, string format, params object[] args)
		{
			WriteLine(client, String.Format(format, args));
		}

		/// <summary>
		/// Writes a line to the log file for the given Client
		/// </summary>
		/// <param name="client">Client connection</param>
		/// <param name="text">Text to write</param>
		public static void WriteLine(Client client, string text)
		{
			WriteLine(client, new string[] { text });
		}

		/// <summary>
		/// Writes multiple lines to the log file for the given Client
		/// </summary>
		/// <param name="client">Client connection</param>
		/// <param name="lines">List of lines to write</param>
		public static void WriteLine(Client client, string[] lines)
		{
			try
			{
				DirectoryInfo di = IOUtility.EnsureDirectory(_OutputDirectory + "\\Clients\\" + client.ToString() + "\\");

				string filePath = IOUtility.GetSafeFilePath(di.FullName + DateTime.Now.ToLongDateString() + ".html", true);

				FileInfo info = new FileInfo(filePath);

				if (!info.Exists)
				{
					info.Create().Close();

					using (StreamWriter writer = new StreamWriter(info.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite), Encoding.Default))
					{

						writer.WriteLine("<HTML>");
						writer.WriteLine("<TITLE>{0}</TITLE>", info.Name);
						writer.WriteLine("<HEAD></HEAD><BODY>");
						writer.WriteLine("<CENTER>");

						writer.Flush();
						writer.Close();
					}
				}

				using (StreamWriter writer = new StreamWriter(info.FullName, true))
				{
					for (int i = 0; i < lines.Length; i++)
					{
						writer.WriteLine("<TABLE WIDTH=\"90%\" CELLSPACING=\"0\" CELLPADDING=\"5\" BORDER=\"1\">");
						writer.WriteLine("<TR><TD WIDTH=\"7%\">");
						writer.WriteLine(DateTime.Now.ToShortTimeString());
						writer.WriteLine("</TD><TD WIDTH=\"93%\">");
						writer.WriteLine(lines[i]);
						writer.WriteLine("</TD></TR>");
						writer.WriteLine("</TABLE>");
					}

					writer.Flush();
					writer.Close();
				}
			}
			catch { }
		}
	}
}
